package com.ibeeking.found.open.b.rest.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.dingtalk.common.bean.DingTalkAccessToken;
import com.dingtalk.common.bean.DingTalkPermanentCodeInfo;
import com.dingtalk.common.error.DingTalkErrorException;
import com.dingtalk.config.DingTalkConfigStorage;
import com.dingtalk.service.DingTalkService;
import com.ibeeking.found.common.constants.AliDingTalkServiceTypeConstant;
import com.ibeeking.found.common.entity.open.*;
import com.ibeeking.found.common.enums.AliDingTalkAppTypeEnum;
import com.ibeeking.found.common.enums.OpenApiConfigEnum;
import com.ibeeking.found.common.enums.WxCpAppTypeEnum;
import com.ibeeking.found.common.utils.DataUtils;
import com.ibeeking.found.common.utils.UrlUtils;
import com.ibeeking.found.common.utils.UserUtils;
import com.ibeeking.gmc.global.api.feign.GlobalOpenFeignClient;
import com.ibeeking.found.open.api.common.param.OpenAuthParam;
import com.ibeeking.found.open.api.feign.GlobalOpenAuthFeignClient;
import com.ibeeking.found.open.api.feign.OpenFileFeignClient;
import com.ibeeking.found.open.b.rest.service.IAliDingTalkOpenEventService;
import com.ibeeking.found.open.b.rest.service.IOpenService;
import com.ibeeking.found.open.b.rest.service.utils.DingCallbackCryptor;
import com.ibeeking.found.open.service.common.constants.DingTalkEventType;
import com.ibeeking.found.open.service.common.constants.RedisKeyConstant;
import com.ibeeking.found.open.service.common.param.QueryOpenAuthInfoParam;
import com.ibeeking.found.open.service.common.vo.OpenAuthViewVO;
import com.ibeeking.found.open.service.common.vo.UrlVO;
import com.ibeeking.found.open.service.config.OpenAuthCallBackConfig;
import com.ibeeking.nematos.exception.BusinessException;
import com.ibeeking.nematos.file.oss.dto.OssPolicyDto;
import com.ibeeking.nematos.log.utils.LogUtils;
import com.ibeeking.nematos.redis.utils.RedisUtils;
import com.ibeeking.nematos.utils.bean.BeanUtil;
import com.ibeeking.nematos.utils.data.Collections3;
import com.ibeeking.nematos.utils.data.StringUtils;
import com.ibeeking.nematos.utils.file.FileUtils;
import com.ibeeking.nematos.utils.json.JsonUtils;
import com.ibeeking.nematos.utils.result.ResponseResult;
import me.chanjar.weixin.common.bean.WxAccessToken;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.cp.bean.WxCpTpPermanentCodeInfo;
import me.chanjar.weixin.cp.config.WxCpTpConfigStorage;
import me.chanjar.weixin.cp.tp.service.WxCpTpService;
import org.apache.commons.lang3.ObjectUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.ArrayList;
import java.util.List;

/**
 * @ClassName AliPayOpenEventServiceImpl
 * @Description
 * @Author ibeeking
 * @Date 2021-06-18 12:21
 **/
@Service("aliOpenEventServiceImpl")
public class AliDingTalkOpenEventServiceImpl implements IAliDingTalkOpenEventService {
    private static final Logger log = LoggerFactory.getLogger(AliDingTalkOpenEventServiceImpl.class);

    //2分钟
    private static final Integer EXPIRE_TIME = 7000; // 100分钟

    @Resource
    private GlobalOpenAuthFeignClient globalOpenAuthFeignClient;

    @Resource
    private OpenFileFeignClient openFileFeignClient;

    @Resource
    private GlobalOpenFeignClient globalOpenFeignClient;

    @Resource
    private IOpenService openServiceImpl;

    @Resource
    private OpenAuthCallBackConfig openAuthCallBackConfig;

    @Resource
    private RedisUtils redisUtils;

    @Override
    public Object msgEvent( HttpServletRequest request, HttpServletResponse response, String timestamp, String nonce, String signature, JSONObject body) {
        try {
            DingTalkService dingTalkService = openServiceImpl.getDefaultDingTalkService();
            DingTalkConfigStorage configStorage = dingTalkService.getDingTalkConfigStorage();
            if(configStorage == null) throw new DingTalkErrorException("读取DingTalkConfigStorage出错！");
            DingCallbackCryptor dingTalkEncryptor = new DingCallbackCryptor(configStorage.getAesToken(),configStorage.getAesKey(), configStorage.getCorpId());

            // 从post请求的body中获取回调信息的加密数据进行解密处理
            String encrypt = body.getString("encrypt");
            String plainText = dingTalkEncryptor.getDecryptMsg(signature, timestamp, nonce, encrypt);
            JSONObject callBackContent = JSON.parseObject(plainText);

            // 根据回调事件类型做不同的业务处理
            String eventType = callBackContent.getString("EventType");
            if (DingTalkEventType.EVENT_CHECK_URL.equals(eventType)) {
                log.info("验证新创建的回调URL有效性: " + plainText);
            } else if (DingTalkEventType.EVENT_CHECK_UPADTE_SUITE_URL.equals(eventType)) {
                log.info("验证更新回调URL有效性: " + plainText);
            } else if (DingTalkEventType.EVENT_SUITE_TICKET.equals(eventType)) {
                // suite_ticket用于用签名形式生成accessToken(访问钉钉服务端的凭证)，需要保存到应用的db。
                // 钉钉会定期向本callback url推送suite_ticket新值用以提升安全性。
                // 应用在获取到新的时值时，保存db成功后，返回给钉钉success加密串（如本demo的return）
                log.info("应用suite_ticket数据推送: " + plainText);
                String suiteId = configStorage.getSuiteId();
                String suitKey = callBackContent.getString("SuiteKey");
                String suiteTicket = callBackContent.getString("SuiteTicket");
                Long timeStamp = callBackContent.getLongValue("TimeStamp");
                LogUtils.info("\nSUITE_TICKET：\n{} ", suiteTicket);
                configStorage.updateSuiteTicket(suiteTicket, 20*60);
                redisUtils.set(RedisKeyConstant.DT_CP_TP_SUITE_TICKET + suiteId, suiteTicket,20*60);
                checkAndUpdateSuiteToken(dingTalkService, suiteId, signature, timestamp, nonce);
                checkAndUpdateAuthorizeAccessToken(dingTalkService, suiteId, signature, timestamp, nonce);
            } else if (DingTalkEventType.EVENT_TMP_AUTH_CODE.equals(eventType)) {
                // 本事件应用应该异步进行授权开通企业的初始化，目的是尽最大努力快速返回给钉钉服务端。用以提升企业管理员开通应用体验
                // 即使本接口没有收到数据或者收到事件后处理初始化失败都可以后续再用户试用应用时从前端获取到corpId并拉取授权企业信息，进而初始化开通及企业。
                log.info("企业授权开通应用事件: " + plainText);
            }  else if (DingTalkEventType.EVENT_USER_ADD_ORG.equals(eventType)) {
                // //通讯录用户增加
                log.info("企业授权开通应用事件: " + plainText);
            }  else {
                // 其他类型事件处理
            }
            // 返回success的加密信息表示回调处理成功
            return dingTalkEncryptor.getEncryptedMap("success", Long.parseLong(timestamp), nonce);
        } catch (Exception e) {
            //失败的情况，应用的开发者应该通过告警感知，并干预修复
            LogUtils.error("process callback fail.", e);
            return "fail";
        }
    }

    /**
     * 获取永久授权码
     *
     * @param queryParam
     * @return
     * @throws Exception
     * @Author ibeeking
     */
    @Override
    public OpenAuthViewVO getDingTalkTpPermanentAuthInfo(QueryOpenAuthInfoParam queryParam) throws Exception {
        LogUtils.info("========queryParam：{}========", JsonUtils.toJsonStr(queryParam));
        if(queryParam == null) throw new BusinessException("无法读取查询参数信息");
        OpenAuthViewVO openAuthViewVO = new OpenAuthViewVO();
        String authCode = queryParam.getAuthCode();
        if(StringUtils.isEmpty(authCode)) throw new BusinessException("获取临时授权码空");

        OssPolicyDto ossPolicyDto = getOssFilePolicy();
        String tenantId = queryParam.getTenantId();
        String state = queryParam.getState();
        String suiteId = queryParam.getComponentAppId();
        String preAuthCodeExpiredIn = queryParam.getExpiresIn();

        OpenAuthParam param = new OpenAuthParam();
        OpenAuthOfExtend openAuthOfExtend = new OpenAuthOfExtend();
        if(StringUtils.isEmpty(tenantId)){
            tenantId = state;
        }
        if(StringUtils.isNotEmpty(tenantId)) {
            param.setTenantId(Long.valueOf(tenantId));
        }

        OpenConfigDTO openConfigDTO = queryOpenConfigByType(OpenApiConfigEnum.OPEN_CONFIG_TYPE_DINGTALK_OPEN.getCode(), AliDingTalkAppTypeEnum.ALIDINGTALK_TP_APP_TYPE_WEB.getCode());

        DataUtils.trueThrowException(openConfigDTO == null, "系统异常:钉钉第三放平台appId为空!");
        LogUtils.info("========openConfigDTO：{}========", JsonUtils.toJsonStr(openConfigDTO));
        String openAppId =  openConfigDTO.getOpenAppId();
        String suiteAppId = openConfigDTO.getComponentAppId();
        param.setOpenId(openConfigDTO.getId());
        param.setConfigType(openConfigDTO.getType());
        param.setConfigSubType(openConfigDTO.getSubType());
        param.setOpenAppId(openAppId);
        param.setComponentAppId(suiteAppId);
        param.setComponentAppSecret(openConfigDTO.getComponentSecret());
        param.setAppToken(openConfigDTO.getComponentMsgToken());
        param.setAppAesKey(openConfigDTO.getComponentMsgAesKey());
        param.setAppType(AliDingTalkAppTypeEnum.ALIDINGTALK_TP_APP_TYPE_WEB.getCode());
        DingTalkService dingTalkTpService = openServiceImpl.getDefaultDingTalkService();
        if(null == dingTalkTpService) throw new BusinessException("钉钉服务初始化还未完成，请稍候再试");
        DingTalkConfigStorage configStorage = dingTalkTpService.getDingTalkConfigStorage();
        String suiteTicket = configStorage.getSuiteTicket();
        if(StringUtils.isEmpty(suiteTicket)){
            String suiteTicketObj = redisUtils.getString(RedisKeyConstant.DT_CP_TP_SUITE_TICKET + suiteAppId);
            if(ObjectUtils.isNotEmpty(suiteTicketObj)) {
                configStorage.updateSuiteTicket(suiteTicketObj, 1200);
            }
        }

        OpenAuthOfAliDingTalkTp openAuthOfAliDingTalkTp = new OpenAuthOfAliDingTalkTp();
        openAuthOfAliDingTalkTp.setSuiteTicket(configStorage.getSuiteTicket());
        openAuthViewVO = BeanUtil.convertBean(param, OpenAuthViewVO.class);
        DingTalkAccessToken suiteAccessTokenEntity = dingTalkTpService.getSuiteAccessTokenEntity(true);
        if(suiteAccessTokenEntity != null) {
            openAuthOfAliDingTalkTp.setSuiteAccessToken(suiteAccessTokenEntity.getAccessToken());
            openAuthOfAliDingTalkTp.setSuiteAccessExpirein(System.currentTimeMillis() + suiteAccessTokenEntity.getExpiresIn() * 1000);
            openAuthOfAliDingTalkTp.setSuiteAccessExpireTime(suiteAccessTokenEntity.getExpiresIn());
            redisUtils.set(RedisKeyConstant.DT_CP_TP_SUITE_ACCESS_TOKEN + suiteAppId, suiteAccessTokenEntity, EXPIRE_TIME.intValue());
            redisUtils.set(RedisKeyConstant.DT_CP_TP_EXPIRE_IN + suiteId, System.currentTimeMillis() + suiteAccessTokenEntity.getExpiresIn() * 1000);
        }

        openAuthOfAliDingTalkTp.setPreAuthCode(authCode);
        DingTalkPermanentCodeInfo dingTalkTpPermanentCodeInfo = dingTalkTpService.getPermanentCodeInfo(authCode);
        LogUtils.info("========DingTalkPermanentCodeInfo：{}========", JsonUtils.toJsonStr(dingTalkTpPermanentCodeInfo));
        String permanentCode  = dingTalkTpPermanentCodeInfo.getPermanentCode();
        redisUtils.set(RedisKeyConstant.DT_CP_TP_PERMANENT_CODE + suiteAppId, permanentCode, EXPIRE_TIME);
        openAuthOfAliDingTalkTp.setPermanentCode(permanentCode);
        DingTalkPermanentCodeInfo.AuthCorpInfo rtnAuthCorpInfo = dingTalkTpPermanentCodeInfo.getAuthCorpInfo();

        //授权企业信息
        if(rtnAuthCorpInfo != null) {
            String authCorpId = rtnAuthCorpInfo.getCorpId();
            OpenAuthOfAliDingTalkTpAuthCorpInfo authCorpInfo = BeanUtil.convertBean(rtnAuthCorpInfo, OpenAuthOfAliDingTalkTpAuthCorpInfo.class);
            authCorpInfo.setCorpid(authCorpId);
            param.setAppId(authCorpId);
            openAuthViewVO.setAppId(authCorpId);
            openAuthViewVO.setName(authCorpInfo.getCorpName());
//            if(StringUtils.isNotEmpty(rtnAuthCorpInfo.getCorpId())) {
//                try {
//                    String fileName = (String.valueOf(System.currentTimeMillis())).concat("_".concat(rtnAuthCorpInfo.getCorpId()).concat("_roundLogo.png"));
//                    String fileTag = ossPolicyDto.getDir() + fileName;
//                    MultipartFile multipartFile = FileUtils.getMultipartFile(rtnAuthCorpInfo.getCorpRoundLogoUrl(), fileName, fileTag);
//                    ResponseResult<String> responseResult = openFileFeignClient.uploadFile(multipartFile);
//                    String fileUploadPath = responseResult.getData();
//                    authCorpInfo.setCorpRoundLogoUrl(UrlUtils.removeUrlDomainName(fileUploadPath));
//                } catch (Exception ex) {
//                    authCorpInfo.setCorpRoundLogoUrl("");
//                }
//            }
//
//            if(StringUtils.isNotEmpty(rtnAuthCorpInfo.getCorpWxQrcode())) {
//                try {
//                    String fileName = (String.valueOf(System.currentTimeMillis())).concat("_".concat(rtnAuthCorpInfo.getCorpId()).concat("_qrcode.png"));
//                    String fileTag = ossPolicyDto.getDir() + fileName;
//                    MultipartFile multipartFile = FileUtils.getMultipartFile(rtnAuthCorpInfo.getCorpWxQrcode(), fileName, fileTag);
//                    ResponseResult<String> responseResult = openFileFeignClient.uploadFile(multipartFile);
//                    String fileUploadPath = responseResult.getData();
//                    authCorpInfo.setCorpWxqrcode(UrlUtils.removeUrlDomainName(fileUploadPath));
//                } catch (Exception ex) {
//                    authCorpInfo.setCorpWxqrcode("");
//                }
//            }
//            openAuthOfWxCpTp.setAuthCorpInfo(authCorpInfo);
//            WxAccessToken corpAccessTokenEntity = wxCpTpService.getCorpToken(authCorpId,permanentCode, true);
//            if(corpAccessTokenEntity != null ){
//                String corpAccessToken = corpAccessTokenEntity.getAccessToken();
//                if(StringUtils.isNotEmpty(corpAccessToken)){
//                    openAuthOfWxCpTp.setCorpAccessToken(corpAccessToken);
//                    openAuthOfWxCpTp.setCorpAccessExpireTime(corpAccessTokenEntity.getExpiresIn());
//                    openAuthOfWxCpTp.setCorpAccessExpirein(System.currentTimeMillis() + corpAccessTokenEntity.getExpiresIn() * 1000);
//                    redisUtils.set(RedisKeyConstant.WX_CP_TP_CORP_ACCESS.concat(suiteAppId).concat(":").concat(authCorpId), corpAccessTokenEntity, EXPIRE_TIME.intValue());
//                }
//            }
//        }
//        // 授权信息
//        WxCpTpPermanentCodeInfo.AuthInfo auThInfo = wxCpTpPermanentCodeInfo.getAuthInfo();
//        if(auThInfo != null) {
//            List<OpenAuthOfWxCpTpAuthAgentInfo> authAgentInfos = new ArrayList<>();
//            List<WxCpTpPermanentCodeInfo.Agent> agentList = auThInfo.getAgents();
//            if(Collections3.isNotEmpty(agentList)) {
//                agentList.stream().forEach(d->{
//                    Integer agentId = d.getAgentId();
//                    OpenAuthOfWxCpTpAuthAgentInfo authAgentInfo = new OpenAuthOfWxCpTpAuthAgentInfo();
//                    authAgentInfo.setAgentid(agentId);
//                    authAgentInfo.setName(d.getName());
//                    authAgentInfo.setAuthMode(d.getAuthMode());
//                    authAgentInfo.setAppid(d.getAppid());
//                    authAgentInfo.setIsCustomizedApp(d.getIsCustomizedApp());
//
//                    WxCpTpPermanentCodeInfo.Privilege privilege = d.getPrivilege();
//                    if(privilege!=null) {
//                        authAgentInfo.setLevel(privilege.getLevel());
//                        List<Integer> allowParties = privilege.getAllowParties();
//                        if(Collections3.isNotEmpty(allowParties)) {
//                            authAgentInfo.setAllowParty(JsonUtils.toJsonStr(allowParties));
//                        }
//                        List<Integer> allowTags = privilege.getAllowTags();
//                        if(Collections3.isNotEmpty(allowTags)) {
//                            authAgentInfo.setAllowTag(JsonUtils.toJsonStr(allowTags));
//                        }
//                        List<String> allowUsers = privilege.getAllowUsers();
//                        if(Collections3.isNotEmpty(allowUsers)) {
//                            authAgentInfo.setAllowUser(JsonUtils.toJsonStr(allowUsers));
//                        }
//                        List<Integer> extraParties = privilege.getExtraParties();
//                        if(Collections3.isNotEmpty(extraParties)) {
//                            authAgentInfo.setExtraParty(JsonUtils.toJsonStr(extraParties));
//                        }
//                        List<Integer> extraTags = privilege.getExtraTags();
//                        if(Collections3.isNotEmpty(extraTags)) {
//                            authAgentInfo.setExtraTag(JsonUtils.toJsonStr(extraTags));
//                        }
//                        List<String> extraUsers = privilege.getExtraUsers();
//                        if(Collections3.isNotEmpty(extraUsers)) {
//                            authAgentInfo.setExtraUser(JsonUtils.toJsonStr(extraUsers));
//                        }
//                    }
//                    if(StringUtils.isNotEmpty(d.getSquareLogoUrl())) {
//                        try {
//                            String fileName = (String.valueOf(System.currentTimeMillis())).concat("_".concat(agentId.toString()).concat("_square.png"));
//                            String fileTag = ossPolicyDto.getDir() + fileName;
//                            MultipartFile multipartFile = FileUtils.getMultipartFile(d.getSquareLogoUrl(), fileName, fileTag);
//                            ResponseResult<String> responseResult = openFileFeignClient.uploadFile(multipartFile);
//                            String fileUploadPath = responseResult.getData();
//                            authAgentInfo.setSquareLogoUrl(UrlUtils.removeUrlDomainName(fileUploadPath));
//                        } catch (Exception ex) {
//                            authAgentInfo.setSquareLogoUrl("");
//                        }
//                    }
//                    if(StringUtils.isNotEmpty(d.getRoundLogoUrl())) {
//                        try {
//                            String fileName = (String.valueOf(System.currentTimeMillis())).concat("_".concat(agentId.toString()).concat("_round.png"));
//                            String fileTag = ossPolicyDto.getDir() + fileName;
//                            MultipartFile multipartFile = FileUtils.getMultipartFile(d.getRoundLogoUrl(), fileName, fileTag);
//                            ResponseResult<String> responseResult = openFileFeignClient.uploadFile(multipartFile);
//                            String fileUploadPath = responseResult.getData();
//                            authAgentInfo.setRoundLogoUrl(UrlUtils.removeUrlDomainName(fileUploadPath));
//                        } catch (Exception ex) {
//                            authAgentInfo.setRoundLogoUrl("");
//                        }
//                    }
//                    authAgentInfos.add(authAgentInfo);
//                });
//                openAuthOfWxCpTp.setAuthAgentInfos(authAgentInfos);
//            }
//        }
//        // 授权管理员信息
//        WxCpTpPermanentCodeInfo.AuthUserInfo rtnAuthUserInfo = wxCpTpPermanentCodeInfo.getAuthUserInfo();
//        if(rtnAuthUserInfo!=null){
//            OpenAuthOfWxCpTpAuthUserInfo wxCpTpAuthUserInfo = BeanUtil.convertBean(rtnAuthUserInfo, OpenAuthOfWxCpTpAuthUserInfo.class);
//            String userAvatar = rtnAuthUserInfo.getAvatar();
//            if(StringUtils.isNotEmpty(userAvatar)) {
//                try {
//                    String fileName = (String.valueOf(System.currentTimeMillis())).concat("_".concat(rtnAuthUserInfo.getName()).concat("_avatar.png"));
//                    String fileTag = ossPolicyDto.getDir() + fileName;
//                    MultipartFile multipartFile = FileUtils.getMultipartFile(userAvatar, fileName, fileTag);
//                    ResponseResult<String> responseResult = openFileFeignClient.uploadFile(multipartFile);
//                    String fileUploadPath = responseResult.getData();
//                    wxCpTpAuthUserInfo.setAvatar(UrlUtils.removeUrlDomainName(fileUploadPath));
//                } catch (Exception ex) {
//                    wxCpTpAuthUserInfo.setAvatar("");
//                }
//            }
//            openAuthOfWxCpTp.setAuthUserInfo(wxCpTpAuthUserInfo);
       }
        openAuthOfExtend.setOpenAuthOfAliDingTalkTp(openAuthOfAliDingTalkTp);
        param.setOpenAuthOfExtend(openAuthOfExtend);
        LogUtils.info("========param：{}========", JsonUtils.toJsonStr(param));
        globalOpenAuthFeignClient.modifyAuth(param);
        openAuthViewVO.setHasOpenAuth(true);
        return openAuthViewVO;//new UrlVO().setUrl(wxOpenCpTpAuthRedirectUrl);
    }

    /**
     * 授权注册页面扫码授权   显示二维码
     *
     * @param request
     * @return
     * @throws Exception
     * @Author ibeeking
     */
    @Override
    public UrlVO getDingTalkTpPreAuthUrl(HttpServletRequest request) throws Exception {
        OpenConfigDTO dtOpenConfigDTO = queryOpenConfigByType(OpenApiConfigEnum.OPEN_CONFIG_TYPE_DINGTALK_OPEN.getCode(), AliDingTalkAppTypeEnum.ALIDINGTALK_TP_APP_TYPE_WEB.getCode());
        DataUtils.trueThrowException(dtOpenConfigDTO == null, "系统异常:钉钉第三放平台appId为空!");
        String corpId =  dtOpenConfigDTO.getOpenAppId();
        String suiteId = dtOpenConfigDTO.getComponentAppId();
        String aliDingTalkAuthRedirectUrl = openAuthCallBackConfig.getAliDingTalkAuthRedirectUrl();
        String tenantId = UserUtils.getTenantId();
        DataUtils.trueThrowException(StringUtils.isBlank(aliDingTalkAuthRedirectUrl), "钉钉第三方授权后的跳转页面尚未配置!");

        DingTalkService dingTalkService = openServiceImpl.getDefaultDingTalkService();
        DingTalkConfigStorage configStorage = dingTalkService.getDingTalkConfigStorage();
        if(configStorage == null) throw new DingTalkErrorException("读取DingTalkConfigStorage出错！");
        LogUtils.info("========DingTalkConfigStorage：{}========", JsonUtils.toJsonStr(configStorage));
        String suiteTicket = configStorage.getSuiteTicket();
        if(StringUtils.isEmpty(suiteTicket)){
            String suiteTicketredis = redisUtils.getString(RedisKeyConstant.DT_CP_TP_SUITE_TICKET + suiteId);
            if(StringUtils.isNotEmpty(suiteTicketredis)) {
                configStorage.updateSuiteTicket(suiteTicketredis, 1200);
            }
        }
        String suiteAccessToken = configStorage.getSuiteAccessToken();
        if(StringUtils.isEmpty(suiteAccessToken)){
            Object suiteAccessObj = redisUtils.get(RedisKeyConstant.DT_CP_TP_SUITE_ACCESS_TOKEN + suiteId);
            if(ObjectUtils.isNotEmpty(suiteAccessObj)) {
                DingTalkAccessToken oldSuiteAccessTokenEntity = (DingTalkAccessToken)suiteAccessObj;
                configStorage.updateSuiteAccessToken(oldSuiteAccessTokenEntity);
            }
        }
        aliDingTalkAuthRedirectUrl = aliDingTalkAuthRedirectUrl + "?corpId=" + corpId + "&suiteId=" + suiteId + "&type=" + AliDingTalkServiceTypeConstant.DT_TYPE_WEB;


        String url = dingTalkService.buildQrConnectUrl(aliDingTalkAuthRedirectUrl, tenantId);
        LogUtils.info("========CallBack result：{}========", JsonUtils.toJsonStr(url));
        return new UrlVO().setUrl(url);
    }

    private void checkAndUpdateSuiteToken(DingTalkService dingTalkTpService, String suiteId, String signature, String timestamp, String nonce){
        DingTalkConfigStorage configStorage = dingTalkTpService.getDingTalkConfigStorage();
        Object objSuiteAccessTokenEntity = redisUtils.get(RedisKeyConstant.DT_CP_TP_SUITE_ACCESS_TOKEN.concat(suiteId));
        if(ObjectUtils.isNotEmpty(objSuiteAccessTokenEntity)) {
            Long oldExpiresIn = redisUtils.getLong(RedisKeyConstant.DT_CP_TP_EXPIRE_IN.concat(suiteId));
            if(oldExpiresIn == null) oldExpiresIn =  System.currentTimeMillis();
            if ((oldExpiresIn - System.currentTimeMillis()) <= 600*1000) {
                try {
                    DingTalkAccessToken newSuiteAccessTokenEntity = dingTalkTpService.getSuiteAccessTokenEntity(true);
                    if (newSuiteAccessTokenEntity != null) {
                        configStorage.updateSuiteAccessToken(newSuiteAccessTokenEntity);
                        redisUtils.set(RedisKeyConstant.DT_CP_TP_SUITE_ACCESS_TOKEN.concat(suiteId), newSuiteAccessTokenEntity, EXPIRE_TIME.intValue());
                        redisUtils.set(RedisKeyConstant.DT_CP_TP_EXPIRE_IN.concat(suiteId), System.currentTimeMillis() + newSuiteAccessTokenEntity.getExpiresIn() * 1000);
                    }
                } catch (DingTalkErrorException ex) {
                    throw new BusinessException("获取suiteAccessToken 出错");
                }
            }
        }else{
            try {
                DingTalkAccessToken newSuiteAccessTokenEntity = dingTalkTpService.getSuiteAccessTokenEntity(true);
                if (newSuiteAccessTokenEntity != null) {
                    configStorage.updateSuiteAccessToken(newSuiteAccessTokenEntity);
                    redisUtils.set(RedisKeyConstant.DT_CP_TP_SUITE_ACCESS_TOKEN.concat(suiteId), newSuiteAccessTokenEntity, EXPIRE_TIME.intValue());
                    redisUtils.set(RedisKeyConstant.DT_CP_TP_EXPIRE_IN.concat(suiteId), System.currentTimeMillis() + newSuiteAccessTokenEntity.getExpiresIn() * 1000);
                }
            } catch (DingTalkErrorException ex) {
                throw new BusinessException("获取suiteAccessToken 出错");
            }
        }

    }

    /**
     * 跟新授权Token
     *
     * @param suiteId
     * @param dingTalkTpService
     */
    private void checkAndUpdateAuthorizeAccessToken(DingTalkService dingTalkTpService, String suiteId, String signature, String timestamp, String nonce) throws Exception{
        List<OpenAuthDTO> openAuthDTOS = queryOpenAuthListByComponentID(suiteId);
        if(Collections3.isNotEmpty(openAuthDTOS)) {
            openAuthDTOS.stream().forEach(openAuthDTO -> {
                try {
                    checkAndUpdateAliDingTalkTpGlobalOpenAuthParam(dingTalkTpService, openAuthDTO, signature, timestamp, nonce);
                } catch (Exception e) {
                    throw new RuntimeException(e);
                }
            });
        }
    }

    /**
     * 跟新授权Token
     *
     * @param dingTalkTpService
     */
    private void checkAndUpdateAliDingTalkTpGlobalOpenAuthParam(DingTalkService dingTalkTpService, OpenAuthDTO openAuthDTO, String signature, String timestamp, String nonce)  throws Exception{
        //更新global OpenAuth
        if (null != openAuthDTO) {
            OpenAuthOfExtend openAuthOfExtend = openAuthDTO.getOpenAuthOfExtend();
            if(openAuthOfExtend == null) throw new BusinessException("读取三方应用配置参数openAuthOfExtend出错！");
            OpenAuthOfAliDingTalkTp openAuthOfAliDingTalkTp = openAuthOfExtend.getOpenAuthOfAliDingTalkTp();
            if(openAuthOfAliDingTalkTp == null) throw new BusinessException("读取三方应用配置参数OpenAuthOfAliDingTalkTp出错！");
            openAuthOfAliDingTalkTp.setSignature(signature);
            openAuthOfAliDingTalkTp.setTimestamp(timestamp);
            openAuthOfAliDingTalkTp.setNonceStr(nonce);
            String permanentCode = openAuthOfAliDingTalkTp.getPermanentCode();
            String appId = openAuthDTO.getAppId();
            String suiteId = openAuthDTO.getComponentAppId();

            DingTalkConfigStorage configStorage = dingTalkTpService.getDingTalkConfigStorage();
            String suiteAccessToken = configStorage.getSuiteAccessToken();

            String suiteTicket = configStorage.getSuiteTicket();
            Boolean needUpdateAccessTokenInDb = false;
            Object oldCorpAccessTokenObj = redisUtils.get(RedisKeyConstant.DT_CP_TP_CORP_ACCESS.concat(suiteId).concat(":").concat(appId));
            if(ObjectUtils.isEmpty(oldCorpAccessTokenObj) ) {
                DingTalkAccessToken newCorpAccessTokenEntity = null;//dingTalkTpService.getAccessToken();
                if (newCorpAccessTokenEntity != null) {
                    configStorage.updateAccessToken(newCorpAccessTokenEntity.getAccessToken(), newCorpAccessTokenEntity.getExpiresIn());
                    redisUtils.set(RedisKeyConstant.DT_CP_TP_CORP_ACCESS.concat(suiteId).concat(":").concat(appId), newCorpAccessTokenEntity, EXPIRE_TIME);
                    String newJsapiTicketOfSuite = dingTalkTpService.getJsapiTicket();
                    if(StringUtils.isNotEmpty(newJsapiTicketOfSuite)){
                        configStorage.updateJsapiTicket(newJsapiTicketOfSuite, newCorpAccessTokenEntity.getExpiresIn());
                    }
                    String newJsapiTicketOfApp = dingTalkTpService.getJsapiTicket();
                    if(StringUtils.isNotEmpty(newJsapiTicketOfApp)){
                        configStorage.updateJsapiTicket(newJsapiTicketOfApp, newCorpAccessTokenEntity.getExpiresIn());
                    }
                    needUpdateAccessTokenInDb = true;
                }

            }else{
                Long corpAccessTokenExpiredIn = openAuthOfAliDingTalkTp.getAccessTokenExpiresIn();
                if (corpAccessTokenExpiredIn == null) corpAccessTokenExpiredIn = System.currentTimeMillis();
                if ((corpAccessTokenExpiredIn - System.currentTimeMillis()) <= 600 * 1000) {
                    DingTalkAccessToken newCorpAccessTokenEntity = null;//dingTalkTpService.getAccessToken(true);
                    if (newCorpAccessTokenEntity != null) {
                        configStorage.updateAccessToken(newCorpAccessTokenEntity.getAccessToken(), newCorpAccessTokenEntity.getExpiresIn());
                        redisUtils.set(RedisKeyConstant.DT_CP_TP_CORP_ACCESS.concat(suiteId).concat(":").concat(appId), newCorpAccessTokenEntity, EXPIRE_TIME);
                        String newJsapiTicketOfSuite = dingTalkTpService.getJsapiTicket();
                        if(StringUtils.isNotEmpty(newJsapiTicketOfSuite)){
                            configStorage.updateJsapiTicket(newJsapiTicketOfSuite, newCorpAccessTokenEntity.getExpiresIn());
                        }
                        String newJsapiTicketOfApp = dingTalkTpService.getJsapiTicket();
                        if(StringUtils.isNotEmpty(newJsapiTicketOfApp)){
                            configStorage.updateJsapiTicket(newJsapiTicketOfApp, newCorpAccessTokenEntity.getExpiresIn());
                        }
                        needUpdateAccessTokenInDb = true;
                    }
                }
            }
            //wxCpTpService.setWxCpTpConfigStorage(wxCpTpConfigStorage);
            LogUtils.info("=======WxCpTpConfigStorage:{}=========",JsonUtils.toJsonStr(configStorage));
            if (needUpdateAccessTokenInDb) {
                //LogUtils.info("\n begin Update WxCpTp OpenAuthParam：\n ");
                OpenAuthParam openAuthParam = BeanUtil.convertBean(openAuthDTO, OpenAuthParam.class);
                openAuthParam.setConfigType(OpenApiConfigEnum.OPEN_CONFIG_TYPE_DINGTALK_OPEN.getCode());
                openAuthParam.setConfigSubType(AliDingTalkAppTypeEnum.ALIDINGTALK_TP_APP_TYPE_WEB.getCode());
                if (StringUtils.isNotEmpty(suiteTicket))
                    openAuthOfAliDingTalkTp.setSuiteTicket(suiteTicket);

                if (StringUtils.isNotEmpty(suiteAccessToken)) {
                    DingTalkAccessToken suiteAccessTokenEntity = configStorage.getSuiteAccessTokenEntity();
                    openAuthOfAliDingTalkTp.setSuiteAccessToken(suiteAccessTokenEntity.getAccessToken());
                    openAuthOfAliDingTalkTp.setSuiteAccessExpireTime(suiteAccessTokenEntity.getExpiresIn());
                    openAuthOfAliDingTalkTp.setSuiteAccessExpirein(System.currentTimeMillis() + suiteAccessTokenEntity.getExpiresIn() * 1000);
                }
                String corpAccessToken = configStorage.getAccessToken();
                if (StringUtils.isNotEmpty(corpAccessToken)) {
                    DingTalkAccessToken corpAccessTokenEntity = null;//configStorage.getAccessToken();
                    openAuthOfAliDingTalkTp.setAccessToken(corpAccessTokenEntity.getAccessToken());
                    openAuthOfAliDingTalkTp.setAccessTokenExpiresTime(corpAccessTokenEntity.getExpiresIn());
                    openAuthOfAliDingTalkTp.setAccessTokenExpiresIn(System.currentTimeMillis() + corpAccessTokenEntity.getExpiresIn() * 1000);
                }
                String suiteJsapiTicket = configStorage.getJsapiTicket();
                if (StringUtils.isNotEmpty(suiteJsapiTicket)) {
                    openAuthOfAliDingTalkTp.setJsapiTicket(suiteJsapiTicket);
                    openAuthOfAliDingTalkTp.setJsapiTicketExpireTime(EXPIRE_TIME);
                    openAuthOfAliDingTalkTp.setJsapiTicketExpirein(System.currentTimeMillis() + EXPIRE_TIME);
                }
                openAuthOfExtend.setOpenAuthOfAliDingTalkTp(openAuthOfAliDingTalkTp);
                openAuthParam.setOpenAuthOfExtend(openAuthOfExtend);
                LogUtils.info("\n update WxCpTp openAuthParam：\n{} ", JsonUtils.toJsonStr(openAuthParam));
                globalOpenAuthFeignClient.modifyAuth(openAuthParam);
            }
        }
    }

    private OpenConfigDTO queryOpenConfigByType(Integer type,Integer subType) {
        OpenConfigQuery query = new OpenConfigQuery();
        query.setType(type);
        query.setSubType(subType);
        ResponseResult<OpenConfigDTO> responseResult = globalOpenFeignClient.queryOpenConfigOne(query);
        return responseResult.getData();
    }

    private OssPolicyDto getOssFilePolicy(){
        ResponseResult<OssPolicyDto> responseResult = openFileFeignClient.policy();
        return responseResult.getData();
    }


    private List<OpenAuthDTO> queryOpenAuthListByComponentID(String suiteId) {
        OpenAuthQuery query = new OpenAuthQuery();
        query.setComponentAppId(suiteId);
        ResponseResult<List<OpenAuthDTO>> responseResult = globalOpenFeignClient.queryOpenAuthList(query);
        return responseResult.getData();
    }

}
